package helpers;

/**
 * @author TRAN NHAT QUANG
 *
 */

import java.io.File;
import java.util.HashSet;

import moore.Moore_Algorithm;
import automaton.DFA;
import brzozowski.Brzozowski;
import exceptions.NotDeterministInitalStateException;
import exceptions.NotDeterministTransitionException;
import exceptions.UnknownInitialStateException;
import exceptions.UnknownTerminalStateException;
import helpers.Stopwatch;
import hopcroft.Hopcroft_Algorithm;
import interfaces.Automaton;


public class RunWithTimeOut implements Runnable{
	Automaton automata;
	int mode = 0; // choose algorithm
	String output = ""; // path of output file
	String input = "";
	
	public RunWithTimeOut(Automaton a, int mode)
	{
		automata = a;
		this.mode = mode;
	}
	
	public RunWithTimeOut(Automaton a)
	{
		automata = a;
		this.mode = 3;
	}
	
	public RunWithTimeOut(String in, String out)
	{
		File f = new File(in);
		automata = FileOperations.readFile(in);
		this.mode = -1;
		this.input = f.getName();
		this.output = out;
	}
	
	@Override
	public void run() {
		switch (this.mode)
		{
			case -1:
				runAllToFile();
				break;
			case 0:
				runBrzozowski();
				break;
			case 1:
				runHopcroft();
				break;
			case 2:
				runMoore();
				break;
			case 3:
				runAll();
				break;
		}
	}
	
	private String runBrzozowski()
	{
		try {
			Stopwatch sw = new Stopwatch();
			
			Brzozowski.doBrzozoski(this.automata);
			
			return "Brzozowski: " + sw.elapsedTime();
		} catch (UnknownInitialStateException | UnknownTerminalStateException
				| NotDeterministInitalStateException
				| NotDeterministTransitionException e) {
			System.out.println(e.getMessage());
		}
		
		return "Brzozowski: Fail";
	}
	
	private String runHopcroft()
	{
		try
		{
			Stopwatch sw = new Stopwatch();
			
			Hopcroft_Algorithm.hopCroft((DFA) this.automata);

			return "Hopcroft: " + sw.elapsedTime();
		}
		catch (Exception ex)
		{
			System.out.println(ex.getMessage());
		}
		
		return "Hopcroft: Fail";
	}
	
	private String runMoore()
	{
		try
		{
			Stopwatch sw = new Stopwatch();
			
			@SuppressWarnings("unused")
			HashSet<HandleHashSet> partitions = Moore_Algorithm.moore_Equivalence((DFA) this.automata);
			
			return "Moore: " + sw.elapsedTime();
		}
		catch (Exception ex)
		{
			System.out.println(ex.getMessage());
		}
		
		return "Moore: Fail";
	}
	
	private void runAll()
	{
		try
		{
			System.out.println(this.runHopcroft());
				
			System.out.println(this.runMoore());
			
			System.out.println(this.runBrzozowski());
		}
		catch (Exception ex)
		{
			System.out.println(ex.getMessage());
		}
	}
	
	private void runAllToFile()
	{
		try
		{
			String ss =this.input+"\n ";
			//System.out.println("============================");	
				
			ss+=this.runHopcroft();
				
			ss+="\n " + this.runMoore();
			
			ss+="\n " + this.runBrzozowski();
			
			FileOperations.saveFile(this.output, ss);
		}
		catch (Exception ex)
		{
			System.out.println(ex.getMessage());
		}
	}

}
